package com.zbkj.client.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zbkj.client.config.ClientTokenComponent;
import com.zbkj.client.config.SSESessionManager;
import com.zbkj.client.dao.MessageMapper;
import com.zbkj.client.service.*;
import com.zbkj.common.exception.CrmebException;
import com.zbkj.common.model.client.agent.Agent;
import com.zbkj.common.model.client.agent.AgentGroup;
import com.zbkj.common.model.client.agent.ContentCreate;
import com.zbkj.common.model.client.agent.UserLocation;
import com.zbkj.common.model.client.digital.CustomDigitalPerson;
import com.zbkj.common.model.client.message.AgentSession;
import com.zbkj.common.model.client.message.Message;
import com.zbkj.common.request.client.AgentSessionAddRequest;
import com.zbkj.common.response.ClientLoginResponse;
import com.zbkj.service.service.AgentGroupService;
import com.zbkj.service.service.AgentService;
import com.zbkj.service.service.AgentSessionService;
import com.zbkj.service.service.UserLocationService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import com.zbkj.common.request.client.SendMessageRequest;
import com.zbkj.common.model.client.message.Dialog;
import com.zbkj.common.model.client.message.DialogMember;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.TextMessage;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;

import com.zbkj.common.response.client.MessageList;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.zbkj.common.vo.MyRecord;

@Slf4j
@Service
public class MessageServiceImpl extends ServiceImpl<MessageMapper, Message> implements MessageService {
    @Autowired
    private DialogService dialogService;
    @Autowired
    private DialogMemberService dialogMemberService;
    @Autowired
    private ObjectMapper objectMapper;

    @Autowired
    private AgentService agentService;

    @Autowired
    private AgentGroupService agentGroupService;

    @Autowired
    private AgentSessionService agentSessionService;

    @Autowired
    private AgentClientService agentClientService;

    @Autowired
    private SSESessionManager sseSessionManager;

    @Value("${workbench.agent}")
    private String agentBaseUrl;

    @Autowired
    private ClientTokenComponent clientTokenComponent;

    @Autowired
    private UserLocationService userLocationService;

    @Autowired
    private ClientLoginService clientLoginService;

    @Autowired
    private RestTemplate restTemplate;

    private List<String> cardShowEventList = Arrays.asList("biz_add_voice","biz_add_video");

    @Override
    public void sendMessage(SendMessageRequest request, HttpServletResponse response, HttpServletRequest httpRequest,Integer userId) throws Exception {
        Integer dialogId = request.getDialogId();
        String type = request.getDialogType() != null ? request.getDialogType() : "agent";
        String content = request.getContent();
        String linkId = request.getLinkId();
        String sessionId = request.getSessionId();
        String agentSessionId = request.getAgentSessionId();

        String token = httpRequest.getHeader("token");
        ClientLoginResponse userInfo = clientTokenComponent.getUserInfo(userId, token);
        Integer merId = userInfo.getMerId();

        //判断用户是否有套餐权限
        Integer linkLevel = 0;
        if ("agent".equals(type)){
            Agent agent = agentService.lambdaQuery()
                    .eq(Agent::getAgentId, linkId)
                    .eq(Agent::getIsDel, 0)
                    .one();
            if (agent != null){
                linkLevel = agent.getPackageLevel();
            }
        }else{
            AgentGroup agentGroup = agentGroupService.lambdaQuery()
                    .eq(AgentGroup::getGroupId, linkId)
                    .eq(AgentGroup::getIsDel, 0)
                    .one();
            if (agentGroup != null){
                linkLevel = agentGroup.getPackageLevel();
            }
        }

        if (userInfo.getPackageLevel() < linkLevel){
            //套餐等级权限不足
            JSONObject packageLevelError = new JSONObject();
            packageLevelError.put("code", 10011);
            packageLevelError.put("msg", "您的套餐无此权限");
            packageLevelError.put("data", null);

            JSONObject packageLevelResultError = new JSONObject();
            packageLevelResultError.put("event", "biz:error");
            packageLevelResultError.put("event_name", "系统错误");
            packageLevelResultError.put("timestamp", java.time.OffsetDateTime.now(java.time.ZoneOffset.UTC).toString());
            packageLevelResultError.put("data", packageLevelError);

            String packageLevelResultErrorString = JSON.toJSONString(packageLevelResultError);

            // 设置SSE响应头
            response.setContentType("text/event-stream; charset=UTF-8");
            response.setCharacterEncoding("UTF-8");
            response.setHeader("Cache-Control", "no-cache");
            response.setHeader("Connection", "keep-alive");
            response.setHeader("Access-Control-Allow-Origin", "*");
            response.setHeader("Access-Control-Allow-Headers", "Cache-Control");

            // 构造SSE格式的数据
            String sseData = "data: " + packageLevelResultErrorString + "\n\n";
            
            // 直接写入HTTP响应流
            response.getWriter().write(sseData);
            response.getWriter().flush();

            Boolean errSend = false;
            if (sessionId != null && !sessionId.isEmpty()) {
                errSend = sseSessionManager.sendRawToSession(sessionId, sseData);
            }
            log.info("套餐权限不足 ，用户:{}, errsend:{}, 返回信息:{}", userId, errSend, packageLevelResultErrorString);
            return;
        }

        // 1. 新建对话框和成员
        if (dialogId == null || dialogId == 0) {
            // 先查询是否已存在相同members和creatorId的对话
            Dialog dialog = insertDialog(request, userId);
            dialogId = dialog.getId();
        }

        //参数传递
        HashMap<String, Object> paramMap = new HashMap<>();
        paramMap.put("dialogId", dialogId);
        paramMap.put("type", type);
        paramMap.put("agentId", linkId);
        paramMap.put("userId", userId);
        paramMap.put("agentSessionId", agentSessionId);
        paramMap.put("merId", merId);

        //把用户信息传递给agent,agent直接调用工具
        HashMap<String, Object> agentUserInfo = new HashMap<>();
        agentUserInfo.put("token", token);

        //传递用户定位信息
        Map<String, Object> userInfoRequestJson = new HashMap<>();

        UserLocation userLocation = userLocationService.getByUserId(userId);
        //用户定位信息可以还未完成，即做了文案创作
        if (userLocation != null) {
            userInfoRequestJson = agentClientService.getAgentUserInfo(userLocation);
        }

        if ("agent".equals(type)){
            chatStream(linkId, content, sessionId,  response,  paramMap, agentSessionId, agentUserInfo, userInfoRequestJson);
        }else{
            groupChatStream(linkId, content, sessionId,  response,  paramMap, agentSessionId, agentUserInfo, userInfoRequestJson);
        }
    }

    @Override
    public List<MessageList> getMessageList(Integer dialogId, Integer page, Integer pagesize) {
        List<Message> messages = this.lambdaQuery()
                .eq(Message::getDialogId, dialogId)
                .eq(Message::getIsDel, 0)
                .orderByDesc(Message::getCreateTime)
                .last("limit " + ((page-1)*pagesize) + "," + pagesize)
                .list();

        List<MessageList> result = new ArrayList<>();
        if (messages != null && !messages.isEmpty()) {
            for (Message msg : messages) {
                MessageList vo = new MessageList();
                vo.setId(msg.getId());
                vo.setDialogId(msg.getDialogId());
                vo.setSenderId(msg.getSenderId());
                vo.setContent(msg.getContent());
                vo.setType(msg.getType());
                vo.setIsAgent(msg.getIsAgent());
                vo.setCreateTime(msg.getCreateTime());
                result.add(vo);
            }
        }
        return result;
    }

    @Override
    public void sendMessageWebSocket(SendMessageRequest request, Integer userId, String token, WebSocketSession session) {
//        Integer dialogId = request.getDialogId();
//        Integer type = request.getType() != null ? request.getType() : 1;
//        String content = request.getContent();
//        List<String> agentIds = request.getMembers();
//        if (userId == null) {
//            try {
//                session.sendMessage(new TextMessage("{\"event\":\"unauthorized\",\"data\":\"未登录\"}"));
//            } catch (Exception ignored) {}
//            return;
//        }
//        if (dialogId == null) {
//            String members = String.join(",", agentIds);
//            Dialog existingDialog = dialogService.lambdaQuery()
//                    .eq(Dialog::getMembers, members)
//                    .eq(Dialog::getCreatorId, userId)
//                    .eq(Dialog::getIsDel, 0)
//                    .one();
//
//            if (existingDialog != null) {
//                dialogId = existingDialog.getId();
//            } else {
//                Dialog dialog = new Dialog();
//                dialog.setCreatorId(userId);
//                dialog.setType(agentIds != null && agentIds.size() > 1 ? 2 : 1);
//                dialog.setName("新对话");
//                dialog.setMembers(members);
//                dialogService.save(dialog);
//                dialogId = dialog.getId();
//                if (agentIds != null) {
//                    for (String agentId : agentIds) {
//                        if (agentId == null || agentId.isEmpty()) continue;
//                        DialogMember member = new DialogMember();
//                        member.setDialogId(dialogId);
//                        if (agentId.startsWith("agent_")) {
//                            String idStr = agentId.substring(6);
//                            member.setUserId(idStr);
//                            member.setIsAgent(1);
//                        } else if (agentId.startsWith("user_")) {
//                            String idStr = agentId.substring(5);
//                            member.setUserId(idStr);
//                            member.setIsAgent(0);
//                        } else {
//                            continue;
//                        }
//                        member.setJoinTime(new Date());
//                        dialogMemberService.save(member);
//                    }
//                }
//                DialogMember self = new DialogMember();
//                self.setDialogId(dialogId);
//                self.setUserId(userId.toString());
//                self.setIsAgent(0);
//                self.setJoinTime(new Date());
//                dialogMemberService.save(self);
//            }
//        }
//        // 保存发送者消息
//        Message msg_send = new Message();
//        msg_send.setDialogId(dialogId);
//        msg_send.setSenderId(userId);
//        msg_send.setType(type);
//        msg_send.setContent(content);
//        msg_send.setIsDel(0);
//        msg_send.setIsAgent(0);
//        msg_send.setCreateTime(new Date());
//        msg_send.setUpdateTime(new Date());
//        this.save(msg_send);
//
//        // 2. 流式请求testAIRes接口并推送到WebSocket前端，同时拼接内容
//        StringBuilder contentBuilder = new StringBuilder();
//        try {
//            URL url = new URL("http://localhost:7081/api/client/message/testAIRes");
//            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
//            conn.setRequestMethod("GET");
//            conn.setRequestProperty("token", token);
//            conn.setDoInput(true);
//            conn.connect();
//            try (BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8))) {
//                String line;
//                while ((line = reader.readLine()) != null) {
//                    if (!line.trim().isEmpty()) {
//                        session.sendMessage(new TextMessage(line));
//                        contentBuilder.append(line).append("\n");
//                        Thread.sleep(100); // 可选，模拟AI流式延迟
//                    }
//                }
//            } finally {
//                conn.disconnect();
//            }
//        } catch (Exception e) {
//            try {
//                session.sendMessage(new TextMessage("{\"event\":\"error\",\"data\":\"AI流式转发失败: " + e.getMessage() + "\"}"));
//            } catch (Exception ignored) {}
//            return;
//        }
//        // 保存流式内容消息
//        Message msg = new Message();
//        msg.setDialogId(dialogId);
//        msg.setSenderId(1); // 固定为1
//        msg.setType(type);
//        msg.setContent(contentBuilder.toString());
//        msg.setIsDel(0);
//        msg.setCreateTime(new Date());
//        msg.setUpdateTime(new Date());
//        this.save(msg);
    }

    /**
     * 插入文案创作记录
     * 根据传入的参数创建并保存ContentCreate记录
     *
     * @param params 包含文案创作相关参数的Map
     */
    @Override
    public Integer insertMessage(Map<String, Object> params) {
        try {
            log.info("开始插入message消息表，参数: {}", params);
            Message message = new Message();

//            AgentSession agentSessionLogicId = insertSession(params);
            // 设置基本信息
            message.setDialogId((Integer) params.get("dialogId"));
            message.setSenderId((Integer) params.get("senderId"));
            message.setType((String) params.get("type"));
            message.setAgentId((String) params.get("agentId"));
//            message.((String) params.get("agentId"));
            message.setIsAgent((Integer) params.get("isAgent"));
            message.setContent((String)params.get("contentResult"));
            message.setSessionId((Integer) params.get("agentSessionLogicId"));
            message.setAgentSessionId((String) params.get("agentSessionId"));
            message.setCardShow((Map<String, Object>) params.get("cardShow"));

            // 保存到数据库
            boolean saveResult = this.save(message);
            log.info("message保存结果: {}, 记录ID: {}", saveResult, message.getId());
            return message.getId();
        } catch (Exception e) {
            log.error("插入message记录失败: {}", e.getMessage(), e);
            return  null;
        }
    }

    //插入session表
    public AgentSession insertSession(Map<String, Object> params) {
        try {
            log.info("开始插入session表，参数: {}", params);
            AgentSession agentSession = agentSessionService.lambdaQuery()
                    .eq(AgentSession::getDialogId, params.get("dialogId"))
                    .eq(AgentSession::getIsDel, 0)
                    .eq(AgentSession::getSessionId, params.get("agentSessionId"))
                    .one();

            if (agentSession == null) {
                agentSession = new AgentSession();
                agentSession.setDialogId((Integer) params.get("dialogId"));
                agentSession.setSessionId((String) params.get("agentSessionId"));

                agentSessionService.save(agentSession);
                log.info("插入session表: {}, 记录ID: {}", params, agentSession.getId());
            }

            return agentSession;
        } catch (Exception e) {
            log.error("插入session记录失败: {}", e.getMessage(), e);
            return null;
        }
    }

    /**
     * 流式聊天API
     * 发送消息到指定的AI代理服务并返回流式响应
     *
     * @param agentId AI代理ID
     * @param message 用户消息
     * @param sessionId SSE会话ID
     * @param response HTTP响应对象
     */
    @Override
    public void chatStream(String agentId, String message, String sessionId, HttpServletResponse response, Map<String, Object> params, String agentSessionId,Map<String, Object> agentUserInfo,Map<String, Object> userLocationInfo) {
        log.info("chatStream开始处理，agentId: {}, message: {}, sessionId: {}, method: {}", agentId, message, sessionId);

        // 设置SSE响应头
        response.setContentType("text/event-stream; charset=UTF-8");
        response.setCharacterEncoding("UTF-8");
        response.setHeader("Cache-Control", "no-cache");
        response.setHeader("Connection", "keep-alive");
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Headers", "Cache-Control");

        try {
            String url = agentBaseUrl + "/api/v1/agents/" + agentId + "/chat/stream";
            log.info("开始请求外部API: {}", url);

            URL urlObj = new URL(url);
            HttpURLConnection connection = (HttpURLConnection) urlObj.openConnection();
            connection.setRequestMethod("POST");
            connection.setRequestProperty("Content-Type", "application/json");
            connection.setDoOutput(true);
            connection.setDoInput(true);
            connection.setConnectTimeout(30000);
            connection.setReadTimeout(300000);

            try (OutputStream os = connection.getOutputStream()) {
                Map<String, Object> requestMap = new HashMap<>();
                requestMap.put("message", message);
                if (agentSessionId != null) {
                    //用户信息可以传空
                    requestMap.put("session_id", agentSessionId);
                }

                if (userLocationInfo != null) {
                    //用户信息可以传空
                    requestMap.put("user_info", userLocationInfo);
                }

                if (agentUserInfo != null) {
                    //用户信息可以传空
                    requestMap.put("biz_user_info", agentUserInfo);
                }

                String jsonRequest = JSON.toJSONString(requestMap);
                os.write(jsonRequest.getBytes("UTF-8"));
                os.flush();
                log.info("已发送请求数据: {}", jsonRequest);
            }

            int responseCode = connection.getResponseCode();
            log.info("外部API响应码: {}", responseCode);

            if (responseCode != 200) {
                throw new RuntimeException("HTTP请求失败，状态码: " + responseCode);
            }


            //将返回头设置x-session-id
            String agentSessionIdRes = null;
            // 获取外部API返回的header中的x-session-id
            agentSessionIdRes = connection.getHeaderField("x-session-id");
            if (agentSessionIdRes != null) {
                log.info("外部API返回的x-session-id(agentSessionId): {}", agentSessionIdRes);
                // 你可以根据需要将agentSessionId传递到response header或params等
                response.setHeader("Access-Control-Expose-Headers", "x-session-id");
                response.setHeader("x-session-id", agentSessionIdRes);
//                if (params != null) {
//                    params.put("agentSessionId", agentSessionIdRes);
//                }
            } else {
                log.info("外部API未返回x-session-id");
            }

            if (agentSessionId == null){
                params.put("agentSessionId", agentSessionIdRes);
            }

            AgentSession agentSessionInsert = insertSession(params);

            //如果agent_session表中没title，就以第一次会话的消息为标题
            String agentSessionoTitle = agentSessionInsert.getTitle();
            if (agentSessionoTitle == null || agentSessionoTitle.isEmpty()) {
                //用第一条消息的前十五个字做为标题
                agentSessionInsert.setTitle(message != null && message.length() > 15 ? message.substring(0, 15) : message);
                agentSessionService.updateById(agentSessionInsert);
            }

            //先插入用户输入的内容到数据库中
            Map<String, Object> userInsertMessage = new HashMap<>();
            userInsertMessage.put("dialogId", params.get("dialogId"));
            userInsertMessage.put("senderId", params.get("userId"));
            userInsertMessage.put("type", params.get("type"));
//            userInsertMessage.put("agentId", agentId);
            userInsertMessage.put("contentResult", message);
            userInsertMessage.put("isAgent", 0);
            userInsertMessage.put("agentSessionId", agentSessionInsert.getSessionId());
            userInsertMessage.put("agentSessionLogicId", agentSessionInsert.getId());

            insertMessage(userInsertMessage);

            try (BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8"))) {
                String line;
                int lineCount = 0;
                StringBuilder contentResult = new StringBuilder(); // 用于拼接完整的content内容

                while ((line = reader.readLine()) != null) {
                    lineCount++;
                    log.debug("接收到第{}行数据: {}", lineCount, line);

                    // 判断是否以"data: "开头
                    if (line.startsWith("data: ")) {
                        try {
                            String jsonData = line.substring(6); // 移除 'data: ' 前缀
                            JSONObject jsonObject = JSON.parseObject(jsonData);

                            // 检查是否是delta事件，方便一会将信息写入到数据库
                            String event = jsonObject.getString("event");
                            if ("delta".equals(event)) {
                                JSONObject data = jsonObject.getJSONObject("data");
                                if (data != null) {
                                    String content = data.getString("content");
                                    if (content != null) {
                                        contentResult.append(content);
                                        log.debug("提取到content内容: {}", content);
                                    }
                                }
                            }
                            
                            // 检查是否是tool_result事件
                            if ("tool_result".equals(event)) {
                                JSONObject data = jsonObject.getJSONObject("data");
                                if (data != null) {
                                    JSONObject toolCall = data.getJSONObject("tool_call");
                                    if (toolCall != null) {
                                        String cardEventName = toolCall.getString("biz_ext");
                                        if (cardShowEventList.contains(cardEventName)) {
                                            // 获取callResult
                                            JSONObject result = toolCall.getJSONObject("result");
                                            if (result != null) {
                                                String jsonString = result.toJSONString();
                                                ObjectMapper mapper = new ObjectMapper();

                                                // 直接转换为 Map
                                                Map<String, Object> eventShowParams = mapper.readValue(
                                                        jsonString,
                                                        new TypeReference<Map<String, Object>>() {}
                                                );

                                                //如果业务返回的是报错信息，则eventShowVo为null
                                                Map<String, Object> eventShowVo = addEventShowParams(eventShowParams, cardEventName);
                                                // 将insertCardData的值作为cardShow的值作为插入表的字段
                                                params.put("cardShow", eventShowVo);
                                                
                                                // 构造卡片展示事件并发送给前端
                                                try {
                                                    if (eventShowVo != null){ //如果业务返回的是报错信息，则eventShowVo为null，则不需要发送SSE给前端
                                                        // 深拷贝eventShowParams对象, 转换为JSON字符
                                                        String cardShowEventJson = getCardShowEventJson(jsonObject, eventShowVo);

                                                        // 直接写入HTTP响应流，同时尝试通过SSE会话发送
                                                        response.getWriter().write(cardShowEventJson + "\n\n");
                                                        response.getWriter().flush();

                                                        // 通过SSE发送给前端
                                                        if (sessionId != null && !sessionId.isEmpty()) {
                                                            sseSessionManager.sendRawToSession(sessionId, cardShowEventJson + "\n\n");
                                                            log.debug("发送卡片展示事件成功，sessionId: {}", sessionId);
                                                        }
                                                    }
                                                } catch (Exception e) {
                                                    log.warn("构造卡片展示事件失败: {}", e.getMessage());
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        } catch (Exception e) {
                            log.warn("解析流式数据失败: {}", e.getMessage());
                        }
                    }

                    // 直接写入HTTP响应流，同时尝试通过SSE会话发送
                    response.getWriter().write(line + "\n");
                    response.getWriter().flush();

                    // 如果提供了sessionId，也尝试通过SSE会话发送
                    if (sessionId != null && !sessionId.isEmpty()) {
                        try {
                            boolean sent = sseSessionManager.sendRawToSession(sessionId, line + "\n");
                            if (sent) {
                                log.debug("SSE透传成功，sessionId: {}", sessionId);
                            } else {
                                log.warn("SSE透传失败，sessionId: {}", sessionId);
                            }
                        } catch (Exception e) {
                            log.warn("SSE透传异常，sessionId: {}, 错误: {}", sessionId, e.getMessage());
                        }
                    }
                }
                log.info("流式处理完成，共处理{}行数据", lineCount);

                // 调用对应的数据库插入方法
                try {
                    // 将拼接的完整字符串放入params
                    params.put("contentResult", contentResult.toString());
                    log.info("准备调用message数据库插入方法, content长度: {}", contentResult.length());

                    params.put("agentSessionLogicId", agentSessionInsert.getId());
                    params.put("isAgent", 1);
                    // 插入回复的数据到数据库中
                    Integer messageId = insertMessage(params);

                    //扣点
                    clientLoginService.updateMerPoint((Integer) params.get("userId"),
                            (Integer)params.get("merId"),
                            "agent",
                            messageId,
                            agentClientService.getMouleName("chat"),
                            "",
                            agentClientService.getPointByDuration("agent", null),
                            null
                    );
                } catch (Exception e) {
                    log.error("数据库插入message失败， 错误: {}", e.getMessage());
                }
            }
        } catch (Exception e) {
            log.error("chatStream处理失败", e);
            try {
                String errorMsg = "[ERROR] " + e.getMessage() + "\n";
                response.getWriter().write(errorMsg);
                response.getWriter().flush();

                // 如果提供了sessionId，也尝试通过SSE会话发送错误信息
                if (sessionId != null && !sessionId.isEmpty()) {
                    try {
                        sseSessionManager.sendRawToSession(sessionId, errorMsg);
                    } catch (Exception ignored) {}
                }
            } catch (Exception ignored) {}
        }
    }


    /**
     * 群组流式聊天API
     * 发送消息到指定的AI代理服务并返回流式响应
     *
     * @param groupId AI代理群组ID
     * @param message 用户消息
     * @param sessionId SSE会话ID
     * @param response HTTP响应对象
     */
    @Override
    public void groupChatStream(String groupId, String message, String sessionId, HttpServletResponse response, Map<String, Object> params, String agentSessionId,Map<String, Object> agentUserInfo,Map<String, Object> userLocationInfo) {
        log.info("chatStream开始处理，agentId: {}, message: {}, sessionId: {}, method: {}", groupId, message, sessionId);

        // 设置SSE响应头
        response.setContentType("text/event-stream; charset=UTF-8");
        response.setCharacterEncoding("UTF-8");
        response.setHeader("Cache-Control", "no-cache");
        response.setHeader("Connection", "keep-alive");
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Headers", "Cache-Control");

        try {
            String url = agentBaseUrl + "/api/v1/groups/" + groupId + "/chat/stream";
            log.info("开始请求外部API: {}", url);

            URL urlObj = new URL(url);
            HttpURLConnection connection = (HttpURLConnection) urlObj.openConnection();
            connection.setRequestMethod("POST");
            connection.setRequestProperty("Content-Type", "application/json");
            connection.setDoOutput(true);
            connection.setDoInput(true);
            connection.setConnectTimeout(30000);
            connection.setReadTimeout(300000);

            try (OutputStream os = connection.getOutputStream()) {
                Map<String, Object> requestMap = new HashMap<>();
                requestMap.put("message", message);
                if (agentSessionId != null) {
                    //用户信息可以传空
                    requestMap.put("session_id", agentSessionId);
                }

                //用户定位信息
                if (userLocationInfo != null) {
                    //用户信息可以传空
                    requestMap.put("user_info", userLocationInfo);
                }

                //给python调用业务方接口的信息
                if (agentUserInfo != null) {
                    //用户信息可以传空
                    requestMap.put("biz_user_info", agentUserInfo);
                }

                String jsonRequest = JSON.toJSONString(requestMap);
                os.write(jsonRequest.getBytes("UTF-8"));
                os.flush();
                log.info("已发送请求数据: {}", jsonRequest);
            }

            int responseCode = connection.getResponseCode();
            log.info("外部API响应码: {}", responseCode);

            if (responseCode != 200) {
                throw new RuntimeException("HTTP请求失败，状态码: " + responseCode);
            }


            //将返回头设置x-session-id
            String agentSessionIdRes = null;
            // 获取外部API返回的header中的x-session-id
            agentSessionIdRes = connection.getHeaderField("x-session-id");
            if (agentSessionIdRes != null) {
                log.info("外部API返回的x-session-id(agentSessionId): {}", agentSessionIdRes);
                // 你可以根据需要将agentSessionId传递到response header或params等
                response.setHeader("Access-Control-Expose-Headers", "x-session-id");
                response.setHeader("x-session-id", agentSessionIdRes);
//                if (params != null) {
//                    params.put("agentSessionId", agentSessionIdRes);
//                }
            } else {
                log.info("外部API未返回x-session-id");
            }

            if (agentSessionId == null){
                params.put("agentSessionId", agentSessionIdRes);
            }

            AgentSession agentSessionInsert = insertSession(params);

            //如果agent_session表中没title，就以第一次会话的消息为标题
            String agentSessionoTitle = agentSessionInsert.getTitle();
            if (agentSessionoTitle == null || agentSessionoTitle.isEmpty()) {
                //用第一条消息的前十五个字做为标题
                agentSessionInsert.setTitle(message != null && message.length() > 15 ? message.substring(0, 15) : message);
                agentSessionService.updateById(agentSessionInsert);
            }

            //先插入用户输入的内容到数据库中
            Map<String, Object> userInsertMessage = new HashMap<>();
            userInsertMessage.put("dialogId", params.get("dialogId"));
            userInsertMessage.put("senderId", params.get("userId"));
            userInsertMessage.put("type", params.get("type"));
//            userInsertMessage.put("agentId", agentId);
            userInsertMessage.put("contentResult", message);
            userInsertMessage.put("isAgent", 0);
            userInsertMessage.put("agentSessionId", agentSessionInsert.getSessionId());
            userInsertMessage.put("agentSessionLogicId", agentSessionInsert.getId());

            //先把用户输入的内容插入表中
            insertMessage(userInsertMessage);

            //读取agent 返回的内容
            try (BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8"))) {
                String line;
                int lineCount = 0;
                // 新增：分段拼接delta内容
                StringBuilder currentContentResult = new StringBuilder();
                String currentAgentId = null;
                boolean hasDelta = false;
                // 新增：跟踪当前消息段中是否有符合条件的tool_result事件
                Map<String, Object> currentCardShow = null;

                while ((line = reader.readLine()) != null) {
                    lineCount++;
                    log.debug("接收到第{}行数据: {}", lineCount, line);

                    // 判断是否以"data: "开头
                    if (line.startsWith("data: ")) {
                        try {
                            String jsonData = line.substring(6); // 移除 'data: ' 前缀
                            JSONObject jsonObject = JSON.parseObject(jsonData);
                            String event = jsonObject.getString("event");
                            if ("delta".equals(event)) {
                                JSONObject data = jsonObject.getJSONObject("data");
                                if (data != null) {
                                    String content = data.getString("content");
                                    if (content != null) {
                                        currentContentResult.append(content);
                                        hasDelta = true;
                                    }
                                    JSONObject agentObj = data.getJSONObject("agent");
                                    if (agentObj != null) {
                                        String agentId = agentObj.getString("id");
                                        if (agentId != null) {
                                            currentAgentId = agentId;
                                        }
                                    }
                                }
                            } else if ("agent_switch".equals(event) || "done".equals(event)) {
                                // 遇到切换或结束，插入一次消息
                                if (hasDelta && currentAgentId != null && currentContentResult.length() > 0) {
                                    Map<String, Object> msgParams = new HashMap<>();
                                    msgParams.put("dialogId", params.get("dialogId"));
                                    msgParams.put("type", params.get("type"));
                                    msgParams.put("agentId", currentAgentId);
                                    msgParams.put("contentResult", currentContentResult.toString());
                                    msgParams.put("isAgent", 1);
                                    msgParams.put("agentSessionId", agentSessionInsert.getSessionId());
                                    msgParams.put("agentSessionLogicId", agentSessionInsert.getId());
                                    // 如果有cardShow数据，添加到msgParams中
                                    msgParams.put("cardShow", currentCardShow);
                                    insertMessage(msgParams);
                                    log.info("已插入一条group agent消息，agentId={}, content.length={}", currentAgentId, currentContentResult.length());
                                }
                                // 重置
                                currentContentResult.setLength(0);
                                currentAgentId = null;
                                hasDelta = false;
                                currentCardShow = null;
                            } else if ("tool_result".equals(event)) {
                                // 检查是否是tool_result事件
                                JSONObject data = jsonObject.getJSONObject("data");
                                //将tool_result结果写入日志中，方便 排查
                                log.info("tool_result的结果是：{}",data.toJSONString());
                                if (data != null) {
                                    JSONObject toolCall = data.getJSONObject("tool_call");
                                    if (toolCall != null) {
                                        String cardEventName = toolCall.getString("biz_ext");
                                        if (cardShowEventList.contains(cardEventName)) {
                                            // 获取callResult
                                            JSONObject result = toolCall.getJSONObject("result");
                                            if (result != null) {
                                                String jsonString = result.toJSONString();
                                                ObjectMapper mapper = new ObjectMapper();

                                                // 将 返回的业务result的结果 转换为 Map
                                                Map<String, Object> eventShowParams = mapper.readValue(
                                                        jsonString,
                                                        new TypeReference<Map<String, Object>>() {}
                                                );

//                                                Map<String, Object> eventShowVo = addEventShowParams(eventShowParams, cardEventName);
//                                                // 将insertCardData的值作为cardShow的值作为插入表的字段
//                                                params.put("cardShow", eventShowVo);

                                                //将insertCardData的值作为cardShow的值作为插入表的字段
                                                currentCardShow = addEventShowParams(eventShowParams, cardEventName);
                                                
                                                // 构造卡片展示事件并发送给前端
                                                try {
                                                    if (currentCardShow != null){
                                                        // 深拷贝eventShowParams对象, 转换为JSON字符
                                                        String cardShowEventJson = getCardShowEventJson(jsonObject, currentCardShow);

                                                        // 直接写入HTTP响应流，同时尝试通过SSE会话发送
                                                        response.getWriter().write(cardShowEventJson + "\n\n");
                                                        response.getWriter().flush();

                                                        // 通过SSE发送给前端
                                                        if (sessionId != null && !sessionId.isEmpty()) {
                                                            sseSessionManager.sendRawToSession(sessionId, cardShowEventJson + "\n\n");
                                                            log.debug("发送卡片展示事件成功，sessionId: {}", sessionId);
                                                        }
                                                    }
                                                } catch (Exception e) {
                                                    log.warn("构造卡片展示事件失败: {}", e.getMessage());
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        } catch (Exception e) {
                            log.warn("解析流式数据失败: {}", e.getMessage());
                        }
                    }

                    // 直接写入HTTP响应流，同时尝试通过SSE会话发送
                    response.getWriter().write(line + "\n");
                    response.getWriter().flush();

                    // 如果提供了sessionId，也尝试通过SSE会话发送
                    if (sessionId != null && !sessionId.isEmpty()) {
                        try {
                            boolean sent = sseSessionManager.sendRawToSession(sessionId, line + "\n");
                            if (sent) {
                                log.debug("SSE透传成功，sessionId: {}", sessionId);
                            } else {
                                log.warn("SSE透传失败，sessionId: {}", sessionId);
                            }
                        } catch (Exception e) {
                            log.warn("SSE透传异常，sessionId: {}, 错误: {}", sessionId, e.getMessage());
                        }
                    }
                }

                //群聊扣点
                AgentGroup agentGroup = agentGroupService.lambdaQuery()
                        .eq(AgentGroup::getGroupId, groupId)
                        .eq(AgentGroup::getIsDel, 0)
                        .last("limit 1")
                        .one();

                clientLoginService.updateMerPoint((Integer) params.get("userId"),
                        (Integer)params.get("merId"),
                        "group",
                        agentGroup.getId(),
                        agentClientService.getMouleName("group"),
                        "",
                        agentClientService.getPointByDuration("group", null),
                        null
                );

                log.info("流式处理完成，共处理{}行数据", lineCount);
            }
        } catch (Exception e) {
            log.error("chatStream处理失败", e);
            try {
                String errorMsg = "[ERROR] " + e.getMessage() + "\n";
                response.getWriter().write(errorMsg);
                response.getWriter().flush();

                // 如果提供了sessionId，也尝试通过SSE会话发送错误信息
                if (sessionId != null && !sessionId.isEmpty()) {
                    try {
                        sseSessionManager.sendRawToSession(sessionId, errorMsg);
                    } catch (Exception ignored) {}
                }
            } catch (Exception ignored) {}
        }
    }

    /**
     *
     * 调用api创建sessionId
     * @param paramMap
     * @return
     */
    @Override
    public Map<String, Object> createSessionApi(Map<String, Object> paramMap){
        String requestUrl = agentBaseUrl + "/api/v1/sessions/";
        HttpHeaders headers = new HttpHeaders();

        HttpEntity<Map<String, Object>> entity = new HttpEntity<>(paramMap, headers);
        ResponseEntity<Map> response = restTemplate.exchange(requestUrl, HttpMethod.POST, entity, Map.class);
        Map<String, Object> respBody = response.getBody();
        if (respBody != null && Integer.valueOf(201).equals(respBody.get("code"))) {
            Map<String, Object> data = (Map<String, Object>)respBody.get("data");

            return data;
        } else {
            throw new CrmebException(respBody != null ? respBody.get("message").toString() : "创建session会话失败");
        }
    }

    /**
     * 删除服务端session
     * @param agentSessionId
     * @return
     */
    @Override
    public Map<String, Object> delSessionApi(String agentSessionId){
        String requestUrl = agentBaseUrl + "/api/v1/sessions/" + agentSessionId;
        HttpHeaders headers = new HttpHeaders();

        HttpEntity<Map<String, Object>> entity = new HttpEntity<>(headers);
        ResponseEntity<Map> response = restTemplate.exchange(requestUrl, HttpMethod.DELETE, entity, Map.class);
        Map<String, Object> respBody = response.getBody();
        if (respBody != null && Integer.valueOf(200).equals(respBody.get("code"))) {
            Map<String, Object> data = (Map<String, Object>)respBody.get("data");

            return data;
        } else {
            throw new CrmebException(respBody != null ? respBody.get("message").toString() : "删除session会话失败");
        }
    }


    /**
     * 创建session会话，先请求调用api接口创建，再创建本地库的sessionId
     * @param sendMessageRequest
     * @return
     */
    @Override
    public AgentSession createSession(SendMessageRequest sendMessageRequest,Integer userId){

        Integer dialogId = sendMessageRequest.getDialogId();

        //如果没有dialog对话框信息，则先创建对话框
        if (dialogId == null || dialogId == 0){
            Dialog dialog = insertDialog(sendMessageRequest, userId);
            dialogId = dialog.getId();
        }

        //取传入的参数，拼接起来调用创建session的agent
        String linkId = sendMessageRequest.getLinkId();

        String dialogType = sendMessageRequest.getDialogType();

        HashMap<String, Object> paramMap = new HashMap<>();

        String sessionType = "single";
        if ("group".equals(dialogType)){
            sessionType = "group";
            paramMap.put("group_id", linkId);
        }else{
            paramMap.put("agent_id", linkId);
        }

        paramMap.put("session_type", sessionType);

        Map<String, Object> sessionApiRes = createSessionApi(paramMap);
        String agentSessionId = (String) sessionApiRes.get("id");

        HashMap<String, Object> insertMap = new HashMap<>();
        insertMap.put("dialogId", dialogId);
        insertMap.put("agentSessionId", agentSessionId);

        //将生成的session信息插入数据库中
        AgentSession agentSession = insertSession(insertMap);

        return agentSession;
    }

    /**
     * 插入dialog表
     * @param request
     * @param userId
     * @return
     */
    @Override
    public Dialog insertDialog(SendMessageRequest request, Integer userId) {
        // 先查询是否已存在相同members和creatorId的对话
        String type = request.getDialogType() != null ? request.getDialogType() : "agent";
        String linkId = request.getLinkId();

        Dialog dialog = dialogService.lambdaQuery()
                .eq(Dialog::getCreatorId, userId)
                .eq(Dialog::getType, type)
                .eq(Dialog::getLinkId, linkId)
                .eq(Dialog::getIsDel, 0)
                .one();

        if (dialog == null) {
            dialog = new Dialog();
            dialog.setCreatorId(userId);
            dialog.setType(type);
            dialog.setLinkId(linkId);

            String name = "新对话";
            //查询agent_id或者group_id
            List<String> members = Arrays.asList(linkId);
            if ("group".equals(type)) {
                AgentGroup agentGroup = agentGroupService.lambdaQuery()
                        .eq(AgentGroup::getGroupId, linkId)
                        .eq(AgentGroup::getIsDel, 0)
                        .one();

                if (agentGroup != null) {
                    members = agentGroup.getAgentIds();
                    name = agentGroup.getTitle();
                }
            } else {
                Agent agent = agentService.lambdaQuery()
                        .eq(Agent::getAgentId, linkId)
                        .eq(Agent::getIsDel, 0)
                        .one();
                if (agent != null) {
                    name = agent.getTitle();
                }
            }

            dialog.setName(name);

            dialog.setMembers(members);
            dialogService.save(dialog);
        }

        return dialog;
    }

    /**
     * 返回聊天框成员的头像
     * @param dialogId
     * @param token
     * @return
     */
    @Override
    public  Map<String, Object> getDialogImgs(Integer dialogId, String token){
        Dialog dialog = dialogService.getById(dialogId);
        Integer userId = dialog.getCreatorId();

        ClientLoginResponse userInfo = clientTokenComponent.getUserInfo(userId, token);
        HashMap<Integer, Object> userMap = new HashMap<>();
        userMap.put(userInfo.getId(), userInfo.getHeadImg());

        List<Agent> agents = agentService.lambdaQuery()
                .eq(Agent::getIsDel, 0)
                .in(Agent::getAgentId, dialog.getMembers())
                .list();

        Map<String, Object> map = new HashMap<>();
        Map<String, Object> agentMap = new HashMap<>();

        for (Agent agent : agents) {
            HashMap<String, Object> agentMapTemp = new HashMap<>();
            agentMapTemp.put("headImg", agent.getHeadImg());
            agentMapTemp.put("title", agent.getTitle());

            agentMap.put(agent.getAgentId(), agentMapTemp);
        }

        map.put("agent", agentMap);
        map.put("user", userMap);

        return map;
    }

    @Override
    public void delAgentSession(SendMessageRequest request) {
        String agentSessionId = request.getAgentSessionId();
        Integer dialogId = request.getDialogId();
        
        log.info("开始删除Agent会话，agentSessionId={}, dialogId={}", agentSessionId, dialogId);
        
        try {
            // 1. 直接更新AgentSession记录（标记is_del为1）
            if (agentSessionId != null && !agentSessionId.isEmpty() && dialogId != null) {
                Boolean agentSessionCount = agentSessionService.lambdaUpdate()
                        .eq(AgentSession::getSessionId, agentSessionId)
                        .eq(AgentSession::getDialogId, dialogId)
                        .eq(AgentSession::getIsDel, 0)
                        .set(AgentSession::getIsDel, 1)
                        .set(AgentSession::getUpdateTime, new Date())
                        .update();
                
                log.info("成功删除AgentSession记录，影响行数={}", agentSessionCount);
            }
            
            // 2. 直接更新Message记录（标记is_del为1）
            if (agentSessionId != null && !agentSessionId.isEmpty() && dialogId != null) {
                Boolean messageCount = this.lambdaUpdate()
                        .eq(Message::getAgentSessionId, agentSessionId)
                        .eq(Message::getDialogId, dialogId)
                        .eq(Message::getIsDel, 0)
                        .set(Message::getIsDel, 1)
                        .set(Message::getUpdateTime, new Date())
                        .update();
                
                log.info("成功删除Message记录，影响行数={}", messageCount);
            }

            //3.删除服务端的会话,先注释
//            delSessionApi(agentSessionId);
//            log.info("成功删除服务端 AgentSession记录，sessionId为：{}", agentSessionId);
            
            log.info("Agent会话删除完成，agentSessionId={}, dialogId={}", agentSessionId, dialogId);
            
        } catch (Exception e) {
            log.error("删除Agent会话失败，agentSessionId={}, dialogId={}", agentSessionId, dialogId, e);
            throw new RuntimeException("删除Agent会话失败", e);
        }
    }

    /**
     * 生成卡片展示的参数
     * @param params
     * @return
     */
    private Map<String, Object> addEventShowParams(Map<String, Object> params, String bizExt){
        String config = "{\n" +
                "\"biz_add_voice\":{\n" +
                    "\"returnType\":\"detail\",\n" +
                    "\"type\":\"audio\",\n" +
                    "\"methodName\":\"addVoice\"\n" +
                    "},\n" +
                "\"biz_add_video\":{\n" +
                    "\"returnType\":\"detail\",\n" +
                    "\"type\":\"video\",\n" +
                    "\"methodName\":\"addVideo\"\n" +
                    "}\n" +
                "}";

        try {
            ObjectMapper mapper = new ObjectMapper();
            Map<String, Object> configMap = mapper.readValue(config, new TypeReference<Map<String, Object>>() {
            });

            Map<String, Object> bizMapConfig = (Map<String, Object>)configMap.get(bizExt);

//            EventShowVo eventShowVo = new EventShowVo();

            Map<String, Object> insertMap = new HashMap<>();
            insertMap.put("returnType", bizMapConfig.get("returnType"));
            insertMap.put("methodName", bizMapConfig.get("methodName"));
            insertMap.put("type", bizMapConfig.get("type"));

//            eventShowVo.setReturnType((String) bizMapConfig.get("returnType"));
//            eventShowVo.setMethodName((String) bizMapConfig.get("methodName"));
//            eventShowVo.setType((String) bizMapConfig.get("type"));

            //拼接业务参数
            Map<String, Object> map = new HashMap<>();
            switch (bizExt){
                case "biz_add_voice":
                    //拼接业务数据
                    String linkId = (String) params.get("taskId");

                    //如果业务返回的是错误信息，这里直接返回null
                    if (linkId == null || linkId.isEmpty()){
                        return null;
                    }

                    map.put("linkId", linkId);
                    break;

                case "biz_add_video":
                    //拼接业务数据
                    Integer id = (Integer) params.get("taskId");

                    //如果业务返回的是错误信息，这里直接返回null
                    if (id == null || id == 0){
                        return null;
                    }

                    map.put("id", id);
                    break;
            }

            insertMap.put("bizRes", map);
//            eventShowVo.setBizRes(map);

            return insertMap;
        }catch (Exception e){
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 将原来返回的流式数据，改下event，增加一个参数data.card_show，拼接成data;{} 格式的字符串数据给前端
     * @param jsonObject
     * @param eventShowVo
     * @return
     */
    private String getCardShowEventJson(JSONObject jsonObject, Map<String, Object> eventShowVo){
        try{
            String jsonStr = jsonObject.toString();
            ObjectMapper mapper = new ObjectMapper();
            Map<String, Object> eventShowParams = mapper.readValue(jsonStr, new TypeReference<Map<String, Object>>() {
            });

            // 深拷贝eventShowParams对象，避免相互影响
            Map<String, Object> newJsonObject = new HashMap<>(eventShowParams);
            log.info("要发送给前端的卡片信息为：{}", eventShowParams);

            // 修改新对象的值，不会影响原对象
            newJsonObject.put("event", "biz:card_show");
            newJsonObject.put("event_name", "卡片展示");

            Map<String, Object> paramData = (Map<String, Object>)eventShowParams.get("data");
            paramData.put("card_show", eventShowVo);

            // 转换为JSON字符串
            String cardShowEventJson = "data: " + JSON.toJSONString(newJsonObject);

            return cardShowEventJson;
        }catch (Exception e){
            return null;
        }
    }
}